package data

import (
	"backend/internal/biz"
	"backend/internal/models"
	"backend/internal/service"
	"context"
	"encoding/json"
	"strconv"
	"time"

	"go.uber.org/zap"
)

const mediaCacheKeyPre = "media:"

type mediaRepo struct {
	data *Data
	log  *zap.Logger
}

func NewMediaRepo(data *Data, log *zap.Logger) service.MediaRepo {
	return &mediaRepo{
		data: data,
		log:  log,
	}
}

func (r *mediaRepo) Create(ctx context.Context, media []*models.Media) ([]*biz.Media, error) {

	if err := r.data.DB(ctx).Create(&media).Error; err != nil {
		return nil, err
	}
	var bizMedia []*biz.Media
	for _, m := range media {
		bizMedia = append(bizMedia, m.ToBiz())
	}
	return bizMedia, nil

}
func (r *mediaRepo) FindByID(ctx context.Context, id uint64) (*biz.Media, error) {
	var m models.Media
	if err := r.data.db.First(&m, id).Error; err != nil {
		return nil, err
	}

	dm := m.ToBiz()
	return dm, nil
}

func (r *mediaRepo) FindCacheByID(ctx context.Context, id uint64) (*biz.Media, error) {
	cacheKey := mediaCacheKeyPre + strconv.FormatUint(id, 10)

	exist := r.data.rdb.Exists(ctx, cacheKey).Val()
	if exist == 1 {
		bytes, err := r.data.rdb.Get(ctx, cacheKey).Bytes()
		if err != nil {
			return nil, err
		}
		var media biz.Media
		err = json.Unmarshal(bytes, &media)
		if err != nil {
			return nil, err
		}

		return &media, nil
	}

	var media models.Media
	err := r.data.db.First(&media, id).Error
	if err != nil {
		return nil, err
	}
	dm := media.ToBiz()
	v, err := json.Marshal(dm)
	if err != nil {
		return nil, err
	}
	r.data.rdb.Set(ctx, cacheKey, v, time.Second*3*24*3600)
	return dm, nil
}

func (r *mediaRepo) DeleteByID(ctx context.Context, id uint64) error {
	cacheKey := mediaCacheKeyPre + strconv.FormatUint(id, 10)
	err := r.data.rdb.Del(ctx, cacheKey).Err()
	if err != nil {
		return err
	}
	err = r.data.DB(ctx).Delete(&models.Media{}, id).Error
	if err != nil {
		return err
	}
	return nil
}

func (r *mediaRepo) DeleteCacheByID(ctx context.Context, id uint64) error {
	cacheKey := mediaCacheKeyPre + strconv.FormatUint(id, 10)
	return r.data.rdb.Del(ctx, cacheKey).Err()

}
